package org.rbac.serv;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.rbac.po.PermissionAuthority;
import org.rbac.po.PermissionAuthorityRefRole;
import org.rbac.po.PermissionRole;
import org.rbac.vo.PermissionControl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * 权限控制
 * <pre>
 * 项目名称：rbac
 * 类名称：PermissionControlServices
 * 类描述：权限控制
 * 创建人：唐家林(tjl)
 * 创建时间：2014年10月9日　下午5:53:26
 * 修改人：
 * 修改时间：
 * 修改备注：
 * @version
 * </pre>
 */
@Service
public class PermissionControlServices extends CommonServices {

	/**
	 * 修改
	 * 
	 * @param pc
	 *            修改的数据
	 * @throws Exception
	 */
	@Transactional(timeout = 20, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void moidify(PermissionControl pc) throws Exception {
		this.edit(pc);
	}
	
	/**
	 * 修改状态
	 * 
	 * @param ids
	 *            修改状态的数据主键
	 * @throws Exception
	 */
	@Transactional(timeout = 20, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void delete(Integer[] ids) throws Exception {
		String hql = "DELETE FROM PermissionAuthorityRefRole parr WHERE parr.id IN (:ids)";
		Query q = getDao().getSession().createQuery(hql);
		q.setParameterList("ids", ids);
		q.executeUpdate();
	}

	/**
	 * 编辑(新增或修改)
	 * 
	 * <pre>
	 * 方法摘要:
	 * 为【多个角色】添加【 多个权限】
	 * 增加的权限已存在,则不添加,否则添加
	 * 
	 * 实现步骤:
	 * 1、获得所有操作的角色,遍历并对遍历出的每一个角色进行一下逻辑
	 * 
	 * 2、获得当前操作的角色,
	 * 3、获取这个角色的所有权限关联
	 * 4、比较传入的权限和这个角色的所有权限,如果该权限已经存在(如果相等),剔除传入的权限,
	 * 5、然后将剩余传入的权限保存
	 * 
	 * 6、对遍历的下一个角色执行2-5步骤
	 * 
	 * PS:步骤2-5单独封装为了一个方法
	 * </pre>
	 * 
	 * @param pc
	 *            操作的数据
	 */
	public void edit(PermissionControl pc) {
		if (null == pc) {
			return;
		}
		
		Integer[] rids = pc.getRid(); // 角色主键
		Integer[] aids = pc.getAid(); // 权限主键
		if (null == rids || null == aids) {
			return;
		}
		
		// 获得选择的所有角色
		String selectPRHql = "SELECT pr FROM PermissionRole pr WHERE pr.id IN (:rids)";
		Query q = getDao().getSession().createQuery(selectPRHql);
		q.setParameterList("rids", rids);
		@SuppressWarnings("unchecked")
		List<PermissionRole> prList = (List<PermissionRole>) q.list();
		q = null;
		
		// 遍历每个角色,并创建其需要新增的权限关联
		for (PermissionRole permissionRole : prList) {
			// 保存当前角色新增的关联关系(方法摘要步骤2-5)
			getDao().saveList( this.createPARROfOneRole(permissionRole, aids) );
		}
	}

	/**
	 * 修改单一角色的权限
	 * 
	 * @param rid
	 *            角色主键
	 * @param aids
	 *            一个或多个权限主键
	 */
	public void editByOneRole(PermissionRole role, Integer[] aids){
		
		// 删除当前角色的所有权限关联
		String deleteHql = "DELETE FROM PermissionAuthorityRefRole parr WHERE parr.permissionRole.id = ?";
		getDao().executeHQL(deleteHql, role.getId());
		
		// 获得选择的所有的权限
		String selectPAHql = "SELECT pa FROM PermissionAuthority pa WHERE pa.id IN (:ids)";
		Query q = getDao().getSession().createQuery(selectPAHql);
		q.setParameterList("ids", aids);
		@SuppressWarnings("unchecked")
		List<PermissionAuthority> paList = (List<PermissionAuthority>) q.list();
		q = null;
		
		// 将角色和选择的权限建立关联
		List<PermissionAuthorityRefRole> parrList = new ArrayList<PermissionAuthorityRefRole>();
		for (PermissionAuthority pa : paList) {
			parrList.add(new PermissionAuthorityRefRole(null, role, pa));
		}
		
		// 保存关联关系
		getDao().saveList(parrList);
	}

	/**
	 * 创建每一个角色需要新增的权限关联
	 * 
	 * @param role
	 *            角色
	 * @param aids
	 *            一个或多个权限主键
	 * @return 返回该角色与新增权限的关联集合
	 */
	private List<PermissionAuthorityRefRole> createPARROfOneRole(PermissionRole role, Integer[] aids){
		Query q = null;
		Session session = getDao().getSession();
		// 获取这个角色的所有权限关联
		String selectPARRHql = "SELECT parr FROM PermissionAuthorityRefRole parr WHERE parr.permissionRole.id = :rid AND parr.permissionAuthority.id IN (:aids)";
		q = session.createQuery(selectPARRHql);
		q.setParameter("rid", role.getId());
		q.setParameterList("aids", aids);
		@SuppressWarnings("unchecked")
		List<PermissionAuthorityRefRole> parrList = (List<PermissionAuthorityRefRole>) q.list();
		q = null;
		
		boolean isAdd = true; // 标记该权限关联是否为需要新增的,true:需要新增的权限关联
		// 遍历出需要新增的权限关联
		List<Integer> aidList = new ArrayList<Integer>();
		for (Integer aid : aids) {
			isAdd = true;
			for (PermissionAuthorityRefRole parr : parrList) {
				if (aid == parr.getPermissionAuthority().getId()) {
					isAdd = false;
					break;
				}
			}
			if (isAdd) {
				aidList.add(aid);
			}
		}
		parrList = new ArrayList<PermissionAuthorityRefRole>();
		
		// 如果没有需要新增的权限,则返回null
		if (aidList.size() == 0) {
			return parrList;
		}
		
		// 获得选择的所有的权限
		String selectPAHql = "SELECT pa FROM PermissionAuthority pa WHERE pa.id IN (:ids)";
		q = session.createQuery(selectPAHql);
		q.setParameterList("ids", aidList);
		@SuppressWarnings("unchecked")
		List<PermissionAuthority> paList = (List<PermissionAuthority>) q.list();
		q = null;
		
		// 创建需要新增的,权限和角色的关联
		for (PermissionAuthority pa : paList) {
			parrList.add(new PermissionAuthorityRefRole(null, role, pa));
		}
		
		// 返回需要新增的,权限和角色的关联
		return parrList;
	}
}
